/**
 * www.easyplatform.cn ©2016
 */
package cn.easyplatform.studio.web.wizards.template;

import cn.easyplatform.entities.beans.list.Header;
import cn.easyplatform.entities.beans.list.ListBean;
import cn.easyplatform.entities.beans.page.PageBean;
import cn.easyplatform.entities.beans.table.TableField;
import cn.easyplatform.lang.Nums;
import cn.easyplatform.lang.Strings;
import cn.easyplatform.studio.StudioApp;
import cn.easyplatform.studio.cmd.entity.CheckCmd;
import cn.easyplatform.studio.cmd.entity.GetEntityCmd;
import cn.easyplatform.studio.utils.StudioUtil;
import cn.easyplatform.studio.utils.WebUtils;
import cn.easyplatform.studio.web.editors.ComponentEditorCallback;
import cn.easyplatform.studio.web.editors.GridEditorCallback;
import cn.easyplatform.studio.web.editors.TableInfo;
import cn.easyplatform.studio.web.editors.support.CodeFormatter;
import cn.easyplatform.studio.web.editors.support.ZulXsdUtil;
import cn.easyplatform.studio.web.views.impl.AbstractView;
import cn.easyplatform.type.EntityType;
import org.apache.commons.lang3.math.NumberUtils;
import org.zkoss.util.resource.Labels;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Components;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.*;
import org.zkoss.zul.impl.XulElement;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @author <a href="mailto:shiny_vc@163.com">陈云亮</a> <br/>
 * @since 2.0.0 <br/>
 */
public class MobilePage2 extends AbstractTemplate {

    private Tabbox tabbox;

    private Tabs tabs;

    private Tabpanels tabpanels;

    private int tabindex;

    protected Intbox pages;

    protected Intbox cols;

    protected TableInfo mainTable;

    private Radiogroup toolbar;

    private Grid canvas;

    private Grid list;

    private Button clear;

    protected TableInfo selectedTable;

    protected String selectedList;

    @Override
    protected void initComponents(Component root) {
        for (Component c : root.getFellows()) {
            if (c instanceof Tabbox)
                tabbox = (Tabbox) c;
            else if (c instanceof Tabs) {
                tabs = (Tabs) c;
                tabs.addEventListener(Events.ON_CLICK, this);
            } else if (c instanceof A || c instanceof Button)
                c.addEventListener(Events.ON_CLICK, this);
            else if (c.getId().equals("tabpanels"))
                tabpanels = (Tabpanels) c;
            else if (c.getId().equals("pages")) {
                pages = (Intbox) c;
                pages.addEventListener(Events.ON_CHANGE, this);
            } else if (c.getId().equals("toolbar")) {
                toolbar = (Radiogroup) c;
            } else if (c.getId().equals("cols")) {
                cols = (Intbox) c;
                cols.addEventListener(Events.ON_CHANGE, this);
            }
        }
        root.getFellow("selectList").addEventListener(Events.ON_CHANGE, this);
        createTabs();
        tabindex=0;
    }

    private void createTabs() {
        Components.removeAllChildren(tabs);
        Components.removeAllChildren(tabpanels);
        for (int i = 1; i <= pages.getValue(); i++) {
            Tab tab = new Tab();
//            tab.setWidth(String.format("%.2f", (10000 / pages.getValue()) / 100.00) + "%");
            tab.setWidth(100.00 / pages.getValue() + "%");
            tab.setHeight("15%");
            tab.setLabel("menu" + i);
            tab.setStyle("border-radius:0");
            tabs.appendChild(tab);
            Tabpanel tabpanel = new Tabpanel();
            tabpanels.appendChild(tabpanel);
        }
    }

    private void createColumns() {
        for (int i = 0; i < cols.getValue(); i++) {
            Column col = new Column();
            Textbox txt = new Textbox("0");
            txt.setTooltiptext(Labels.getLabel("wizard.width"));
            txt.addEventListener(Events.ON_CHANGE, this);
            txt.setHflex("1");
            col.appendChild(txt);
            Combobox cbx = new Combobox();
            cbx.appendChild(new Comboitem("left"));
            cbx.appendChild(new Comboitem("center"));
            cbx.appendChild(new Comboitem("right"));
            cbx.setTooltiptext(Labels.getLabel("wizard.align"));
            cbx.addEventListener(Events.ON_CHANGE, this);
            cbx.setReadonly(true);
            cbx.setSelectedIndex(0);
            cbx.setHflex("1");
            col.appendChild(cbx);
            canvas.getColumns().appendChild(col);
        }
    }

    private void redraw() {
        if (mainTable == null)
            return;
        Iterator<TableField> itr = mainTable.getFields().iterator();
        while (itr.hasNext()) {
            Row row = new Row();
            for (int i = 0; i < cols.getValue(); i++) {
                if (itr.hasNext()) {
                    TableField tf = itr.next();
                    row.appendChild(new Label(tf.getDescription()));
                    if (row.getChildren().size() == cols.getValue()) {
                        canvas.getRows().appendChild(row);
                        row = new Row();
                    }
                    XulElement input = WebUtils.createComponent(tf);
                    input.setTooltiptext(tf.getName());
                    input.setHflex("1");
                    row.appendChild(input);
                    if (row.getChildren().size() == cols.getValue()) {
                        canvas.getRows().appendChild(row);
                        row = new Row();
                    }
                } else {
                    canvas.getRows().appendChild(row);
                    break;
                }
            }
        }
    }

    @Override
    protected void dispatch(Event evt) {
        Component c = evt.getTarget();
        if (c instanceof Tabs) {
            tabindex = ((Tabbox) c.getParent()).getSelectedIndex();
            for (Component comp : tabpanels.getChildren().get(tabindex).getFellows()) {
                if (comp.getId().equals("canvas" + tabindex))
                    canvas = (Grid) comp;
                else if (comp.getId().equals("list" + tabindex))
                    list = (Grid) tabpanels.getFellow("list" + tabindex);
            }
        } else if (c.getId().equals("pages")) {
            createTabs();
        } else if (c.getId().equals("table")) {
            createGrid("canvas");
            createColumns();
            AbstractView.createTableView(
                    new GridEditorCallback(canvas,
                            Labels.getLabel("wizard.table")), true, evt.getTarget())
                    .doOverlapped("right,center");
        } else if (c.getId().equals("clear")) {
            Components.removeAllChildren(tabpanels.getChildren().get(tabindex));
        } else if (c == canvas) {
            mainTable = (TableInfo) evt.getData();
            canvas.getRows().getChildren().clear();
            redraw();
        } else if (c == cols) {
            canvas.getColumns().getChildren().clear();
            canvas.getRows().getChildren().clear();
            createColumns();
            redraw();
        } else if (c.getParent() instanceof Column) {
            setColumnProperty(c);
        } else if (c == list) {
            selectedTable = (TableInfo) evt.getData();
            onCreate(list, selectedTable);
            selectedList = null;
        } else if (c.getId().equals("selectList")) {
            createGrid("list");
            if (evt.getName().equals(Events.ON_CLICK)) {
                AbstractView.createComponentView(
                        new ComponentEditorCallback(c,
                                ((Button) c).getLabel()),
                        EntityType.DATALIST.getName(), c).doHighlighted();
            } else {
                this.selectedList = (String) evt.getData();
                onSelect(list, selectedList);
                selectedTable = null;
            }
        } else if (c.getId().equals("addList")) {
            createGrid("list");
            AbstractView.createTableView(
                    new GridEditorCallback(list,
                            Labels.getLabel("wizard.table")), true, evt.getTarget())
                    .doOverlapped("right,center");
        }
    }

    private void createGrid(String comp) {
        Grid grid = new Grid();
        grid.setWidth("100%");
        grid.setSclass("noborder");
        grid.setId(comp + tabindex);
        Columns columns = new Columns();
        columns.appendChild(new Column());
        grid.appendChild(columns);
        if (comp.equals("canvas")) {
            if (canvas != null)
                tabpanels.getChildren().get(tabindex).removeChild(canvas);
            canvas = grid;
            canvas.addEventListener(Events.ON_CHANGE, this);
            Rows rows = new Rows();
            grid.appendChild(rows);
        } else {
            if (list != null)
                tabpanels.getChildren().get(tabindex).removeChild(list);
            list = grid;
            list.addEventListener(Events.ON_CHANGE, this);
        }
        tabpanels.getChildren().get(tabindex).appendChild(grid);
    }

    private void setColumnProperty(Component c) {
        Column col = (Column) c.getParent();
        if (c instanceof Combobox) {
            col.setAlign(((Combobox) c).getSelectedItem().getLabel());
        } else {
            Textbox tbx = (Textbox) c;
            if (!Strings.isBlank(tbx.getValue())) {
                int width = Nums.toInt(tbx.getValue(), 0);
                if (width > 0)
                    col.setWidth(width + "px");
                else
                    col.setWidth(tbx.getValue());
            } else {
                col.setWidth(null);
            }
        }
        col.invalidate();
    }

    protected String getContent() {
        StringBuilder sb = new StringBuilder();
        sb.append("<tabbox hflex=\"1\" vflex=\"1\" >");
        sb.append("<tabs hflex=\"1\" >");
        for (Component co:tabs.getChildren()){
            sb.append("<tab label=\"").append(((Tab) co).getLabel()).append("\" ");
            sb.append("width=\"").append(((Tab) co).getWidth()).append("\" ");
            sb.append("style=\"").append(((Tab) co).getStyle()).append("\" >");
            sb.append("</tab>");
        }
        sb.append("</tabs>");
        sb.append("<tabpanels hflex=\"1\" vflex=\"1\" >");
        int i=0;
        for (Component comp:tabpanels.getChildren()){
            sb.append("<tabpanel>");
            sb.append("<vlayout>");
            for (Component cp:comp.getChildren()){
                if (cp.getId().equals("canvas"+i)){
                    sb.append("<grid sclass=\"noborder\" oddRowSclass=\"none\" >")
                            .append("<columns>");
                    for (Component c : ((Grid) cp).getColumns().getChildren()) {
                        sb.append("<column ");
                        String width = ((Textbox) c.getFirstChild()).getValue().trim();
                        if (!width.equals("") && !width.equals("0")) {
                            sb.append("width=\"").append(width);
                            if (NumberUtils.isNumber(width))
                                sb.append("px");
                            sb.append("\"");
                        }
                        String align = ((Combobox) c.getLastChild()).getSelectedItem()
                                .getLabel();
                        if (!align.equals("left"))
                            sb.append(" align=\"").append(align).append("\"");
                        sb.append("/>");
                    }
                    sb.append("</columns>");
                    sb.append("<rows>");
                    String value = toolbar.getSelectedItem().getValue();
                    String[] pos = null;
                    if (!value.equals("")) {
                        pos = value.split(",");
                        if (pos[0].equals("top"))
                            buildToolbar(sb, pos[1]);
                    }
                    for (Component row : ((Grid) cp).getRows().getChildren()) {
                        sb.append("<row>");
                        for (Component c : row.getChildren()) {
                            sb.append("<").append(c.getDefinition().getName());
                            if (c instanceof Label)
                                sb.append(" value=\"").append(((Label) c).getValue())
                                        .append("\"");
                            else
                                sb.append(" id=\"#{")
                                        .append(((XulElement) c).getTooltiptext())
                                        .append("}\" ").append(" hflex=\"1\"");
                            sb.append("/>");
                        }
                        sb.append("</row>");
                    }
                    if (pos != null && pos.length == 2 && pos[0].equals("bottom"))
                        buildToolbar(sb, pos[1]);
                    sb.append("</rows>");
                    sb.append("</grid>");
                }

                if (cp.getId().equals("list"+i)){
                    sb.append("<datalist entity=\"").append(selectedList).append("\"");
                    sb.append(
                            " vflex=\"1\" durable=\"true\" event=\"open('U')\"")
                            .append(" showRowNumbers=\"true\" pageSize=\"20\"")
                            .append(" sizedByContent=\"true\" span=\"true\"/>");
                }
            }
            i++;
            sb.append("</vlayout>");
            sb.append("</tabpanel>");
        }
        sb.append("</tabpanels>");
        sb.append("</tabbox>");

        return CodeFormatter.formatXML(ZulXsdUtil.buildDocument(sb.toString()));
    }


    protected void onSelect(Grid list, String id) {
        ListBean bean = (ListBean) StudioApp.execute(new GetEntityCmd(id));
        list.getColumns().getChildren().clear();
        for (Header header : bean.getHeaders()) {
            Column col = new Column();
            col.appendChild(new Label(header.getTitle()));
            col.setTooltiptext(header.getName());
            col.setAlign(header.getAlign());
            col.setStyle(header.getStyle());
            col.setIconSclass(header.getIconSclass());
            col.setImage(header.getImage());
            if (!Strings.isBlank(header.getWidth()))
                col.setWidth(header.getWidth());
            list.getColumns().appendChild(col);
        }
    }

    protected void onCreate(Grid list, TableInfo selectedTable) {
        list.getColumns().getChildren().clear();
        for (TableField tf : selectedTable.getFields()) {
            Column col = new Column();
            col.setTooltiptext(tf.getName());
            col.appendChild(new Label(tf.getDescription()));
            list.getColumns().appendChild(col);
        }
    }

    protected void buildToolbar(StringBuilder sb, String align) {
        sb.append("<row").append(" spans=\"").append(cols.getValue())
                .append("\"");
        if (align.equals("center"))
            sb.append(" align=\"center\"");
        else if (align.equals("right"))
            sb.append(" align=\"right\"");
        sb.append(">").append("<div>");
        ;
        sb.append("<button label=\"").append(Labels.getLabel("button.add"))
                .append("\" event=\"create()\"")
                .append(" iconSclass=\"z-icon-plus\"/>");
        sb.append("<button label=\"").append(Labels.getLabel("button.delete"))
                .append("\" event=\"remove();pageList.reload()\"")
                .append(" iconSclass=\"z-icon-minus\"/>");
        sb.append("<button label=\"").append(Labels.getLabel("button.save"))
                .append("\" event=\"save();pageList.reload()\"")
                .append(" iconSclass=\"z-icon-save\"/>");
        sb.append("</div>").append("</row>");
    }


    @Override
    public PageBean getEntity() {
        save();
        PageBean pb = new PageBean();
        pb.setTable(mainTable == null ? null : mainTable.getTable());
        pb.setAjax(getContent());
        return pb;
    }

    protected void save() {
        if (selectedTable != null) {
            ListBean bean = new ListBean();
            bean.setTable(selectedTable.getTable());
            bean.setId(fetchId());
            bean.setType(EntityType.DATALIST.getName());
            bean.setName((String) list.getRoot().getAttribute("name"));
            List<Header> headers = new ArrayList<Header>();
            for (TableField tf : selectedTable.getFields()) {
                Header header = new Header();
                header.setField(tf.getName());
                header.setName(tf.getName());
                header.setTitle(tf.getDescription());
                header.setType(tf.getType());
                headers.add(header);
            }
            bean.setHeaders(headers);
            StudioUtil.save(bean, 'C');
            this.selectedList = bean.getId();
        }
    }

    protected String fetchId() {
        String id = (String) list.getRoot().getAttribute("id");
        if (id.length() > 4) {
            // 功能ID：SYSCOM50
            // 页面ID：SYSCOM50PY01
            // 列表ID：SYSCOM50QY01
            // 子表列表：SYSCOM50QY02
            // 子表页面：SYSCOM50PY02
            String suffix = id.substring(id.length() - 4, id.length());
            String preffix = id.substring(0, id.length() - 4);
            if (suffix.startsWith("PY")
                    && NumberUtils.isNumber(suffix.substring(2))) {// 符合id命名规范
                for (int i = 1; i <= 99; i++) {
                    String entityId = preffix + "QY" + (i < 10 ? "0" + i : i);
                    if (!StudioApp.execute(new CheckCmd(entityId))) {
                        id = entityId;
                        break;
                    }
                }
            } else {// 不符合规范的,在页面id的基础上从01开始累加
                for (int i = 1; i <= 99; i++) {
                    String entityId = id + (i < 10 ? "0" + i : i);
                    if (!StudioApp.execute(new CheckCmd(entityId))) {
                        id = entityId;
                        break;
                    }
                }
            }
        } else {// 不符合规范的,在页面id的基础上从01开始累加
            for (int i = 1; i <= 99; i++) {
                String entityId = id + (i < 10 ? "0" + i : i);
                if (!StudioApp.execute(new CheckCmd(entityId))) {
                    id = entityId;
                    break;
                }
            }
        }
        return id;
    }
}
